package com.web.managedbean;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;

import org.hibernate.exception.ConstraintViolationException;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DualListModel;
import org.primefaces.model.chart.ChartModel;
import org.springframework.stereotype.Controller;

import com.constants.Constants;
import com.database.bean.Agent;
import com.database.bean.AgentType;
import com.database.bean.CompanyRoundDecisionAndResult;
import com.database.bean.Game;
import com.database.bean.News;
import com.database.bean.Product;
import com.database.bean.ReportDecision;
import com.database.bean.Round;
import com.database.bean.Setting;
import com.database.bean.Supplier;
import com.database.bean.User;
import com.math.util.CalculationUtil;
import com.math.util.ColumnModel;
import com.math.util.GaussianNumberGenerator;
import com.math.util.InitializationBean;
import com.math.util.StatisticBean;
import com.security.util.SecurityUtil;
import com.simulation.SimulationEngine;

@ManagedBean(name="adminMBean")
@SessionScoped
@Controller
public class AdminMBean extends AbstractManagedBean {
	
	private static final long serialVersionUID = 1L;
	private List<Game> allGames=null;
	private List<Product> allProducts=null;
	private List<Supplier> allSuppliers=null;
	private List<User> gameUsers=null;
	private List<Agent> agentTypeAgents=null;
	private Game selectedGame=null;
	private Round selectedRound=null;
	private Product selectedProduct=null;
	private Supplier selectedSupplier=null;
	private AgentType selectedAgentType=null;
	private User selectedUser=null;
	private DualListModel<User> usersPickList=null;
	private List<Setting> settings=null;
	
	//Agent Values
	private int agentMeanPricePreference=0;
	private int agentMeanQualityPreference=0;
	private int agentMeanImagePreference=0;
	private int agentNumberGeneration=0;
	private String agentName="";
	
	//User Values
	private String userName="";
	private String userMail="";
	private String userPassword="";
	private boolean setPassword=false;
	private boolean setImageBudget=false;
	private Double userImage=null;
	private Double userBudget=null;
	
	//Game Values	
	private String gameName="";
	private Date startDate;
	private Integer roundTime=24;
	private Integer numberRounds=10;
	private Integer gameUsersAmount=0;
	
	//Round Values
	private Date roundStartDate;
	private Date roundEndDate;
	private Integer roundNumber;
	
	//Charts
	private ChartModel chartData=null;
	
	//News
	private String newsText=null;
	private String gameId=null;

	//Product
	private String productName=null;
	private Double productImageFactor =null;
	private Double productQualityFactor =null;
	private Double productCosts =null;
	private String productSupplierId=null;
	private boolean productActive=true;
	
	//Supplier
	private String supplierName=null;
	private Double supplierDiscountPer10Units=null;
	private Double supplierDeliveryCosts=null;
	private boolean supplierActive=true;
	
	//Table
	private List<StatisticBean> tableData=null;
	private List<ColumnModel> columns = new ArrayList<ColumnModel>();
	private List<SelectItem> reportOptions;
	private List<SelectItem> chartOptions;
	private String selectedReportOption;
	private String selectedChartOption;
	private String chartType;

	@PostConstruct
	public void init() {

		// SelectOneMenu-Box initialization
		reportOptions = new ArrayList<SelectItem>();
		reportOptions.add(new SelectItem(Constants.OPTION_ALL_ROUND_DATA));
		reportOptions.add(new SelectItem(Constants.OPTION_ALL_AGENT_DATA)); 
		reportOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_PRODUCT)); 
		reportOptions.add(new SelectItem(Constants.OPTION_ALL_PRODUCTS_FROM_SUPPLIERS)); 
		reportOptions.add(new SelectItem(Constants.OPTION_ALL_AGENTTYPE_COMPANY_SALES)); 
		
		
		chartOptions = new ArrayList<SelectItem>();
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_BUDGET));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_IMAGE));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_TOPSELLER));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_IMAGE_EVOLUTION));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_SELLING_EVOLUTION));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_ROUND_BUDGET));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_ROUND_REVENUE));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_ROUND_MARKETING_INVESTMENT));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_ROUND_EDUCATION_INVESTMENT));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_ROUND_OVERDRAFT_COSTS));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_ROUND_LOGISTIC_COSTS));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_PORTFOLIO_RISING));
		chartOptions.add(new SelectItem(Constants.OPTION_ALL_COMPANY_ROUND_AGENTTYPE));

		this.selectedReportOption=Constants.OPTION_ALL_ROUND_DATA;
		this.selectedChartOption=Constants.OPTION_ALL_COMPANY_BUDGET;
		
	}
	
	
	public DualListModel<User> getUsersPickList() {
		List<User> allUsers = new ArrayList<User>();
        List<User> usersToGame = new ArrayList<User>();
       
        allUsers=this.userService.getAllUsers();
       
        this.usersPickList = new DualListModel<User>(allUsers, usersToGame);  
		return this.usersPickList;
	}

	public void setUsersPickList(DualListModel<User> usersPickList) {
		this.usersPickList = usersPickList;
	}

	public AdminMBean() {
		super();
	}
	
	public List<Game> allGames() {
		if(allGames==null)
			this.allGames=this.adminService.getAllGames();
		return this.allGames;
	}
	
	/**
	 * Saving and refreshing the CompanyProductList, especially to 
	 * update the selling price.
	 * @return
	 */
	public void actionSaveAndRefreshAllAgents(ActionEvent actionEvent){
		for (Agent agent : this.agentTypeAgents) {
			this.adminService.update(agent);
		}
		this.agentTypeAgents=this.adminService.getAgentsWithAgentTypeId(this.selectedAgentType.getId());
		this.addInfoMessage(Constants.CMB_AGENT_UPDATE);
	}
	
	public void actionRefreshAllAgentTypeAgents(){
		this.agentTypeAgents=this.adminService.getAgentsWithAgentTypeId(this.selectedAgentType.getId());
	}
	
	public List<Agent> agentTypeAgents() {
		if(this.agentTypeAgents==null || this.agentTypeAgents.size()==0)
			this.agentTypeAgents=this.adminService.getAgentsWithAgentTypeId(this.selectedAgentType.getId());
		return this.agentTypeAgents;
	}
	
	public List<Product> allProducts() {
		if(allProducts==null)
			this.allProducts=this.adminService.getAllProducts();
		return this.allProducts;
	}
	
	public int getAgentMeanPricePreference() {
		return agentMeanPricePreference;
	}

	public void setAgentMeanPricePreference(int agentMeanPricePreference) {
		this.agentMeanPricePreference = agentMeanPricePreference;
	}

	public int getAgentMeanQualityPreference() {
		return agentMeanQualityPreference;
	}

	public void setAgentMeanQualityPreference(int agentMeanQualityPreference) {
		this.agentMeanQualityPreference = agentMeanQualityPreference;
	}

	public int getAgentMeanImagePreference() {
		return agentMeanImagePreference;
	}

	public void setAgentMeanImagePreference(int agentMeanImagePreference) {
		this.agentMeanImagePreference = agentMeanImagePreference;
	}

	public int getAgentNumberGeneration() {
		return agentNumberGeneration;
	}

	public void setAgentNumberGeneration(int agentNumberGeneration) {
		this.agentNumberGeneration = agentNumberGeneration;
	}

	public List<User> selectedGameUsers() {
		return this.gameUsers;
	}
	
	public void actionRefreshAllGames(){
		this.allGames=this.adminService.getAllGames();
	}
	
	public void actionRefreshAllProducts(){
		this.allProducts=this.adminService.getAllProducts();
	}
	
	public void actionRefreshAllSuppliers(){
		this.allSuppliers=this.adminService.getAllSuppliers();
	}
	
	
	public Map<String,String> getAllGamesDropDown(){
		HashMap<String,String> games=this.adminService.getGameDropdown();
		return games;
	}

	public Map<String,String> getAllSuppliersDropDown(){
		HashMap<String,String> games=this.adminService.getSuppliersDropdown();
		return games;
	}
	
	public Game getSelectedGame() {
		return selectedGame;
	}

	public void setSelectedGame(Game selectedGame) {
		this.selectedGame = selectedGame;
	}
	
	public void eventGameRowSelect(SelectEvent event) {  
		Game game=(Game) event.getObject();
		this.selectedGame=game;
		List<User> list = new ArrayList<User>();
		if(this.selectedGame!=null){
			Set<User> set=this.selectedGame.getUsers();
			list=new ArrayList<User>(set);
		}
		this.gameUsers=list;
		//addInfoMessage("Game: "+game.getName());
    } 
	
	
	public void eventRoundRowSelect(SelectEvent event) {  
		Round round=(Round) event.getObject();
		this.selectedRound=round;
		//addInfoMessage("Round: "+round.getRoundNumber());
    } 
	
	public void eventAgentTypeRowSelect(SelectEvent event) {  
		AgentType agentType=(AgentType) event.getObject();
		this.selectedAgentType=agentType;
		//addInfoMessage("Round: "+round.getRoundNumber());
    } 
	
	public void test(){
		System.out.println("AdminMBean Aufruf");
	}
	
	/**
	 * Calculate and Update new Image-Value for the companies
	 * @param simulationRound
	 */
	public void calculateAndUpdateNewImage(Round simulationRound){
		User company = null;
		
		//marketing total
		double mt = 0.0;
		//marketing company
		double mc = 0.0;
		//RD total 
		double rdt = 0.0;
		//rd company
		double rdc = 0.0;
		//personal total 
		double pt = 0.0;
		//personal company
		double pc = 0.0;
		//market share total (unit based)
		double mst = 0.0;
		//market share company
		double msc = 0.0;
		
		//RCIS = 0,25*(MC/MT) + 0,25*(RDC/RDT) + 0,25*(PC/PT) + 0,25*(MSC/MST) )
		//RCIS...Relative Company Image Spending
		double rcis = 0.0;
		//TCIS...Total Company Image Spending SUM(RCIS) 
		double tcis = 0.0;
		//ACIS...Average company image spending ... ACIS=TCIS/N
		double acis = 0.0;
		//ABS(1+(RCIS-ACIS/TCIS)*Image/or value)
		
		double oldImage;
		double newImage;
		
		//factor marketing
		double factorMarketing = 0.25;
		double factorPersonal = 0.25;
		double factorRD = 0.25;
		double factorMarketShare = 0.25;
		
		Setting setting = adminService.getSetting();
		Double alpha = setting.getExponentialSmoothingFactor();
		double startImage = setting.getStartImageForCompanies();
		
		List<StatisticBean> decisions = this.adminService.getMarketGameDecisionsAtRound(simulationRound);
		if(decisions!=null && decisions.size() > 0){
			StatisticBean sBean = decisions.get(0);
			if(sBean!=null){
				mt = sBean.getDecres_marketingInvestment();
				rdt = sBean.getDecres_rdInvestment();
				pt = sBean.getDecres_employerEducationInvestment();
				//mst = sBean.getDecres_revenue();
			}
		}
		
		factorMarketing = setting.getFactorMarketing();
		factorPersonal = setting.getFactorPersonal();
		factorRD = setting.getFactorRD();
		factorMarketShare = setting.getFactorMarketShare();
		
		//calculate mst ... market share total (unit based)
		for (CompanyRoundDecisionAndResult decres : simulationRound
				.getCompanyRoundDecisionAndResults()){
			mst = mst + decres.getAmountSoldProducts();
		}
		
		for (CompanyRoundDecisionAndResult decres : simulationRound
				.getCompanyRoundDecisionAndResults()) {
			company = decres.getUser();
			//1. get all done decisions (investments)
			mc = decres.getMarketingInvestment();
			rdc = decres.getRdInvestment();
			pc = decres.getEmployerEducationInvestment();
			msc = company.getAmountSoldProducts();
			
			
			rcis = 0.0;
			
			if(mt!=0.0){
				rcis = rcis + factorMarketing * (mc/mt);
			}
			if(rdt!=0.0){
				rcis = rcis + factorRD * (rdc/rdt);
			}
			if(pt!=0.0){
				rcis = rcis + factorPersonal * (pc/pt);
			}
			if(mst!=0.0){
				rcis = rcis + factorMarketShare * (msc/mst);
			}
			
			decres.setRcis(rcis);
			
			tcis = tcis + rcis;

		}
		
		acis = tcis/simulationRound.getCompanyRoundDecisionAndResults().size();
		
		for (CompanyRoundDecisionAndResult decres : simulationRound
				.getCompanyRoundDecisionAndResults()) {
			rcis = decres.getRcis();
			company = decres.getUser();
			oldImage = decres.getUser().getImageValue();
			newImage = alpha * oldImage + (1-alpha)*(startImage + rcis - acis);
			
			newImage = CalculationUtil.roundDouble(newImage, 3);
			
			if(newImage<0){
				newImage = 0.0;
			}else if(newImage > 1){
				newImage = 1.0;
			}
			
			company.setImageValue(newImage);
			this.adminService.update(company);
			
			decres.setNewImage(newImage);
			this.adminService.update(decres);
		}
	}
	
	/**
	 * Calculate and Update new budget for the companies
	 * @param simulationRound
	 */
	private void calculateAndUpdateBudget(Round simulationRound) {
		User company = null;
		Double expenses = null;
		Double profit = null;
		Double budget = null;
		Double overdraftCosts = null;
		Double logisticCosts = null;
		
		Setting setting = adminService.getSetting();
		
		for (CompanyRoundDecisionAndResult crdr : simulationRound.getCompanyRoundDecisionAndResults()) {
			company = crdr.getUser();
			expenses = 0.0;
			profit = 0.0;
			budget = 0.0;
			overdraftCosts = 0.0;
			logisticCosts = 0.0;
			
			if (crdr.getMarketingInvestment() != null) {
				expenses += crdr.getMarketingInvestment();
				company.addMarketingBudget(crdr.getMarketingInvestment());
			}
			if (crdr.getEmployerEducationInvestment() != null) {
				expenses += crdr.getEmployerEducationInvestment();
				company.addEmployerEducationBudgetBudget(crdr
						.getEmployerEducationInvestment());
			}
			if (crdr.getRdInvestment() != null) {
				expenses += crdr.getRdInvestment();
				company.addRDBudget(crdr.getRdInvestment());
			}
			
			Double reportCosts = 0.0;
			if(crdr.getReportDecisions()!=null){
				for(ReportDecision repDec:crdr.getReportDecisions()){
					reportCosts += repDec.getReport().getReportPrice();
				}
			}
			expenses += reportCosts;
			
			if (crdr.getExpenses() != null) {
				expenses += crdr.getExpenses();
			}
			
			//calculate logistic-costs if product sortiment is too big
			if(crdr.getCompanyProducts()!=null){
				int nrProducts = crdr.getCompanyProducts().size();
				logisticCosts = CalculationUtil.calculateLogisticCosts(nrProducts,setting);
				expenses += logisticCosts;
			}
			
			//profit = revenue - expenses (all round values)
			profit = crdr.getRevenue() - expenses;
			//add (-)profit of actual budget
			budget = company.getBudget() + profit;
			
			//if budget is negative then there are overdraftCosts
			if(budget<0){
				overdraftCosts = Math.abs(budget)*setting.getInterestRate();
				budget = budget - overdraftCosts;
			}
			
			company.setBudget(budget);
			crdr.setOverdraftCosts(overdraftCosts);
			crdr.setLogisticCosts(logisticCosts);
			crdr.setNewBudget(budget);
			crdr.setReportCosts(reportCosts);
			this.adminService.update(crdr);
			this.adminService.update(company);
			
		}
	}
	
	public String actionStartSimulation(){
		System.out.println("------ Simulation ------");
		
		Round simulationRound=this.selectedRound;
		Game game=simulationRound.getGame();
		
		//Load from Database once again to be sure that everything is up to date in the objects
		
		try{
			game=(Game)adminService.refresh(game);
			simulationRound=(Round)adminService.refresh(simulationRound);
		}
		catch(Throwable t){
			this.addWarningMessage("Some Error occured on refreshing the Game! Please reload all Games before Simulation!");
			return "";
		}
		
		List<User> users=game.getUserList();
		List<AgentType> agentTypes=simulationRound.getAgentTypes();
		List<Agent> agents=new ArrayList<Agent>();
		
		if(agentTypes.size()==0){
			this.addErrorMessage("Please provide AgentTypes for the market simulation!");
		}
		else if(users.size()==0){
			this.addErrorMessage("Please provide Users for the market simulation!");
		}
		else{

			//generate all Agents based of the AgentType Configuration for the selected Round
			for(AgentType at : agentTypes){
				List<Agent> atAgents=adminService.getAgentsWithAgentTypeId(at.getId());
				if(atAgents!=null){
					agents.addAll(atAgents);
				}
			}
			
			if(agents.size()==0){
				this.addErrorMessage("Please provide Agents for the market simulation! Maybe Recreate AgentTypes!");
			}
			else{
				//SimulationEngine erzeugen
				SimulationEngine se=new SimulationEngine();
				se.setAdminService(adminService);
				se.addAgents(agents);
				
				System.out.println("------ Simulation started! ------");
				System.out.println(agents.size() +" Agents werden simuliert!");
				
				//set the new calculated Image out of the company Investments
				//and the revenue market share
				this.calculateAndUpdateNewImage(simulationRound);
				
				//old version: generation in Simulation -> now it is on agentType creation
				//List<Agent> agents=se.generateAndAddAgentsByAgentType(agentTypes);
				
				//simulieren
				se.doSimulationStep(game, simulationRound);
				
				simulationRound.setPlayed(true);
				this.adminService.update(simulationRound);
				
				//Ergebnisse sammeln bzw. Werte anpassen - offen noch Kosten
				//important Date calculated and transfer settings to next round if available
				this.calculateAndUpdateBudget(simulationRound);
				this.createNewCompanyRoundDecisionAndResults(game,simulationRound);
				this.createNewAgentTypesAndAgents(game,simulationRound);
				

				//setPlayed in List
				for(Round r:this.selectedGame.getRounds()){
					if(r.getId()==simulationRound.getId()){
						r.setPlayed(simulationRound.isPlayed());
					}
				}
				
				
				try{
					this.selectedGame=(Game)adminService.refresh(this.selectedGame);
				}
				catch(Throwable t){
					allGames=null;
				}
				
				
				this.addInfoMessage("Simulation ended successfully! Please refresh the Game!");				
			}
		}
		allGames=null;
		return "adminGameManagement?faces-redirect=true";
	}
	
	/**
	 * 
	 * @param prevRound
	 */
	private void createNewAgentTypesAndAgents(Game game,Round prevRound){
		if(prevRound!=null){
			List<AgentType> agentTypes=prevRound.getAgentTypes();
			Round nextRound = null;
			if (game!=null){
				nextRound = game.getNextRoundFromRound(prevRound); 
				if(nextRound!=null){
					for (AgentType agentType : agentTypes) {
						List<Agent> agents=adminService.getAgentsWithAgentTypeId(agentType.getId());
						agentType.setId(null);
						agentType.setAgents(null);
						agentType.setRound(nextRound);
						this.adminService.update(agentType);  //save it
						nextRound.addAgentType(agentType); //add it to list
						for(Agent agent:agents){
							agent.setId(null);
							agent.setCompanyProduct(null);
							agent.setAgentType(agentType);
							this.adminService.update(agent);
						}
					}
				}
			}
		}
		
	}
	
	
	/**
	 * 
	 * @param prevRound
	 */
	private void createNewCompanyRoundDecisionAndResults(Game game,Round prevRound){
		
		if(prevRound!=null){
			CompanyRoundDecisionAndResult copyDecRes=null;
			Round nextRound = null;
			if (game!=null){
				nextRound = game.getNextRoundFromRound(prevRound); 
				if(nextRound!=null){
					for (CompanyRoundDecisionAndResult decres : prevRound.getCompanyRoundDecisionAndResults()) {
						copyDecRes = decres.getCopy(nextRound);
						this.adminService.update(copyDecRes);
						nextRound.addCompanyRoundDecisionAndResut(copyDecRes);
					}
				}
			}
		}
		
	}
	
	public String actionShowUsers() {
		if(this.selectedGame==null){
			addErrorMessage("No Game found!");
			return null;
		}
		else{
			return "adminUserManagement?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	public String actionShowRounds() {
		if(this.selectedGame==null){
			addErrorMessage("No Game found!");
			return null;
		}
		else{
			return "adminRoundManagement?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	public String actionShowAgentTypes() {
		if(this.selectedRound==null){
			addErrorMessage("No Round found!");
			return null;
		}
		else{
			return "adminAgentTypeManagement?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	public String actionShowAgents() {
		if(this.selectedAgentType==null){
			addErrorMessage("No AgentType found!");
			return null;
		}
		else{
			return "adminAgentManagement?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	public String actionGoToUpdateAgentType() {
		if(this.selectedAgentType==null){
			addErrorMessage("No AgentType found!");
			return null;
		}
		else{
			this.agentMeanImagePreference=(int)(this.selectedAgentType.getMeanImage()*100);
			this.agentMeanPricePreference=(int)(this.selectedAgentType.getMeanPrice()*100);
			this.agentMeanQualityPreference=(int)(this.selectedAgentType.getMeanQuality()*100);
			this.agentNumberGeneration=this.selectedAgentType.getAmount();
			this.setAgentName(this.selectedAgentType.getAgentName());
			
			return "adminAgentTypeUpdate?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	public String actionGoToUpdateGame() {
		if(this.selectedGame==null){
			addErrorMessage("No Game found!");
			return null;
		}
		else{
			this.selectedGame=(Game)adminService.refresh(this.selectedGame); //refresh to be sure that everything is up to date
			allGames=null;
			
			this.gameName=this.selectedGame.getName();
			
			return "adminGameUpdateName?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	public String actionGoToUpdateRound() {
		if(this.selectedRound==null){
			addErrorMessage("No Round found!");
			return null;
		}
		else{
			int index=this.selectedGame.getRounds().indexOf(selectedRound);
			this.selectedGame.getRounds().remove(selectedRound);
			this.selectedRound=(Round)adminService.refresh(selectedRound); //refresh to be sure that everything is up to date
			this.selectedGame.getRounds().add(index,selectedRound);
			
			this.roundNumber=this.selectedRound.getRoundNumber();
			this.roundStartDate=this.selectedRound.getStartDate();
			this.roundEndDate=this.selectedRound.getEndDate();
			
			return "adminRoundUpdate?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	public String actionGoToUpdateProduct() {
		if(this.selectedProduct==null){
			addErrorMessage("No Product found!");
			return null;
		}
		else{
			this.productName=this.selectedProduct.getName();
			this.productImageFactor=this.selectedProduct.getImageFactor();
			this.productQualityFactor=this.selectedProduct.getQualityFactor();
			this.productCosts=this.selectedProduct.getProductCosts();
			this.productSupplierId=this.selectedProduct.getSupplier().getId().toString();
			this.productActive=this.selectedProduct.isActive();
			
			return "adminProductUpdate?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	
	public String actionGoToUpdateSupplier() {
		if(this.selectedSupplier==null){
			addErrorMessage("No Supplier found!");
			return null;
		}
		else{
			this.supplierName=this.selectedSupplier.getSupplierName();
			this.supplierDiscountPer10Units=this.selectedSupplier.getDiscountPerTenUnits();
			this.supplierDeliveryCosts=this.selectedSupplier.getDeliveryCost();
			this.supplierActive=this.selectedSupplier.isActive();

			return "adminSupplierUpdate?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	
	public String actionGoToUpdateUser() {
		if(this.selectedUser==null){
			addErrorMessage("No User found!");
			return null;
		}
		else{
			this.selectedGame.getUsers().remove(selectedUser);
			this.selectedUser=(User)adminService.refresh(selectedUser); //refresh to be sure that everything is up to date
			this.selectedGame.getUsers().add(selectedUser);
			
			
			this.userName=this.selectedUser.getNickname();
			this.userMail=this.selectedUser.getEmail();
			this.userBudget=this.selectedUser.getBudget();
			this.userImage=this.selectedUser.getImageValue();
			this.userPassword="";
			
			return "adminUserUpdate?faces-redirect=true";  //verwenden um auf andere Seite zu gehen
		}
    }
	
	public String actionGoToCreateAgentType(){
		this.agentMeanImagePreference=0;
		this.agentMeanPricePreference=0;
		this.agentMeanQualityPreference=0;
		this.agentName="";
		this.agentNumberGeneration=0;
		this.selectedAgentType=new AgentType();
		this.selectedAgentType.setRound(this.selectedRound);
		return "adminAgentTypeUpdate?faces-redirect=true";
	}
	
	
	public String actionGoToCreateGame(){
		this.gameName=null;
		this.startDate=null;
		this.roundTime=24;
		this.numberRounds=10;
		this.gameUsersAmount=0;
		
		return "adminGameUpdate?faces-redirect=true";
	}
	
	
	public String actionGoToCreateUser(){
		this.userName=null;
		this.userMail=null;
		this.userBudget=null;
		this.userImage=null;
		this.userPassword=null;
		this.setPassword=true;
		this.setImageBudget=false;
		
		this.selectedUser=new User();
		Setting setting = adminService.getSetting();
		this.selectedUser.setBudget(setting.getStartBudgetForCompanies());
		this.selectedUser.setImageValue(setting.getStartImageForCompanies());
		this.userImage=setting.getStartImageForCompanies();
		this.userBudget=setting.getStartBudgetForCompanies();
		
		this.selectedUser.setGame(this.selectedGame);
		
		return "adminUserUpdate?faces-redirect=true";
	}
	
	
	public String actionGoToCreateRound(){
		Integer highestRoundNumber=0;
		if(this.selectedGame.getRounds()!=null){
			for(Round round:this.selectedGame.getRounds()){
				if(highestRoundNumber==null){
					highestRoundNumber=round.getRoundNumber();
				}
				else if(round.getRoundNumber() > highestRoundNumber){
					highestRoundNumber=round.getRoundNumber();
				}
			}
		}
		else{
			highestRoundNumber=0;
		}
		
		this.roundNumber=(highestRoundNumber+1);
		this.selectedRound=new Round();
		this.selectedRound.setGame(this.selectedGame);
		
		return "adminRoundUpdate?faces-redirect=true";
	}
	
	public String actionGoToCreateProduct(){
		this.productCosts=0.0;
		this.productImageFactor=0.0;
		this.productQualityFactor=0.0;
		this.productName="";
		this.productActive=true;
		this.productSupplierId=(String)this.getAllSuppliersDropDown().values().toArray()[0];
		
		this.selectedProduct=new Product();
		
		return "adminProductUpdate?faces-redirect=true";
	}
	
	public String actionGoToCreateSupplier(){
		this.supplierName="";
		this.supplierDiscountPer10Units=null;
		this.supplierDeliveryCosts=null;
		this.supplierActive=true;
		
		this.selectedSupplier=new Supplier();
		
		return "adminSupplierUpdate?faces-redirect=true";
	}
	
	
	public String actionDeleteAgentType(){
		this.adminService.delete(this.selectedAgentType);		
		this.selectedRound.removeAgentType(this.selectedAgentType);
		
		//delete Agents for old AgentType if change
		if(this.selectedAgentType.getId()!=null){
			adminService.deleteAgentWithAgentTypeId(this.selectedAgentType.getId());
		}
		
		this.addInfoMessage("Deleted!");
		return "adminAgentTypeManagement?faces-redirect=true";
	}
	
	public String actionDeleteRound(){
		this.adminService.delete(this.selectedRound);
		this.selectedGame.removeRound(this.selectedRound);
		this.addInfoMessage("Deleted!");
		return "adminRoundManagement?faces-redirect=true";
	}

	public String actionDeleteUser(){
		this.adminService.delete(this.selectedUser);
		this.selectedGame.removeUser(this.selectedUser);
		//this.selectedGame=(Game)this.adminService.refresh(this.selectedGame);		
		this.addInfoMessage("Deleted!");
		return "adminUserManagement?faces-redirect=true";
	}
	
	public String actionDeleteSupplier(){
		this.adminService.delete(this.selectedSupplier);
		allSuppliers=null;
		allProducts=null;
		//this.selectedGame=(Game)this.adminService.refresh(this.selectedGame);		
		this.addInfoMessage("Deleted!");
		return "adminSupplierManagement?faces-redirect=true";
	}
	
	public String actionDeleteProduct(){
		this.adminService.delete(this.selectedProduct);
		allProducts=null;
		//this.selectedGame=(Game)this.adminService.refresh(this.selectedGame);		
		this.addInfoMessage("Deleted!");
		return "adminProductManagement?faces-redirect=true";
	}
	
	public String actionDeleteGame(){
		this.adminService.delete(this.selectedGame);
		this.selectedGame=null;
		this.allGames=this.adminService.getAllGames();
		
		return "adminGameManagement?faces-redirect=true";
	}
	
	/*
	 * Wird nicht mehr benötigt -> nur mehr Empfehlung wieviele Agents
	 *
	public void generateAgentTypes(int amountAgents,Round round,Setting setting){
		int amountAgentType1=(int)Math.round(((double)amountAgents)*0.35); //evtl in settings
		int amountAgentType2=(int)Math.round(((double)amountAgents)*0.50); //evtl in settings
		int amountAgentType3=(int)Math.round(((double)amountAgents)*0.15); //evtl in settings	
		
		//35%
		AgentType t1=new AgentType();
		t1.setAgentName("LowPrice");
		t1.setMeanImage(0.0);
		t1.setMeanPrice(1.0);
		t1.setMeanQuality(0.0);
		t1.setAmount(amountAgentType1);
		t1.setRound(round);
		adminService.update(t1);
		round.addAgentType(t1);
		generateAndSaveAgentFromAgentType(t1,setting);
	
		//50%
		AgentType t2=new AgentType();
		t2.setAgentName("Middle");
		t2.setMeanImage(0.5);
		t2.setMeanPrice(0.5);
		t2.setMeanQuality(0.5);
		t2.setAmount(amountAgentType2);
		t2.setRound(round);
		adminService.update(t2);
		round.addAgentType(t2);
		generateAndSaveAgentFromAgentType(t2,setting);
		
		//15%
		AgentType t3=new AgentType();
		t3.setAgentName("HighQualityImage");
		t3.setMeanImage(1.0);
		t3.setMeanPrice(0.0);
		t3.setMeanQuality(1.0);
		t3.setAmount(amountAgentType3);
		t3.setRound(round);
		adminService.update(t3);
		round.addAgentType(t3);
		generateAndSaveAgentFromAgentType(t3,setting);
	}
	*/
	
	public String actionInitializeGame(){
		System.out.println("Start initialization!");
		Game game=this.selectedGame;
		//Round firstRound=game.getFirstRound();	
		Setting setting=adminService.getSetting();
		
		try{
			List<User> users=game.getUserList();
			int amountUsers=users.size();
			int agentCompanyFactor=(int)Math.round(setting.getAgentAmountCompanyFactor());
			int amountAgents=amountUsers*agentCompanyFactor;
			
			//generate AgentTypes and Agents
			//after meeting on 22.5. with professor not needed anymore
			//generateAgentTypes(amountAgents, firstRound, setting);
			
			List<Product> products = this.adminService.getAllActiveProducts();
			InitializationBean initBean = CalculationUtil.calculateInitialValues(products, amountUsers, amountAgents, setting);
			this.adminService.saveInitialization(initBean);
			
			setting = this.adminService.getSetting();
			for(User usr:users){
				usr.setBudget(setting.getStartBudgetForCompanies());
				this.userService.updateUser(usr);
			}
			
			this.addInfoMessage("Initialization ended successfully! Please refresh the Game!");	
		}catch(RuntimeException rte){
			rte.printStackTrace();
			this.addErrorMessage("An Error occured during the Initialization!");	
		}
		
		allGames=null;
		return "adminGameManagement?faces-redirect=true";
	}


	public String getMeanWeightingText(){
		double sum=this.agentMeanImagePreference+this.agentMeanPricePreference+this.agentMeanQualityPreference;
		double weightMeanImage=0;
		double weightMeanQuality=0;
		double weightMeanPrice=0;
		
		if(sum!=0){
			weightMeanImage=CalculationUtil.roundDouble(this.agentMeanImagePreference/sum,3);
			weightMeanQuality=CalculationUtil.roundDouble(this.agentMeanQualityPreference/sum,3);
			weightMeanPrice=CalculationUtil.roundDouble(this.agentMeanPricePreference/sum,3);
		}
		
		StringBuffer sb=new StringBuffer();
		sb.append("Weighting Price: "+weightMeanPrice+"\n");
		sb.append("Weighting Quality: "+weightMeanQuality+"\n");
		sb.append("Weighting Image: "+weightMeanImage);
		
		return sb.toString();
	}
	
	public String actionUpdateAgentType() {
		try{
			
			double sumPreferences=this.agentMeanImagePreference+this.agentMeanPricePreference+this.agentMeanQualityPreference;
			if(sumPreferences==0){
				this.addErrorMessage("Set at least one Preference!");
				return "";
			}
			
			//delete Agents for old AgentType if change
			if(this.selectedAgentType.getId()!=null){
				adminService.deleteAgentWithAgentTypeId(this.selectedAgentType.getId());
			}
			
			
			this.selectedAgentType.setAgentName(this.agentName);
			this.selectedAgentType.setMeanImage((double)((double)this.agentMeanImagePreference/100));
			this.selectedAgentType.setMeanPrice((double)((double)this.agentMeanPricePreference/100));
			this.selectedAgentType.setMeanQuality((double)((double)this.agentMeanQualityPreference/100));
			this.selectedAgentType.setAmount(agentNumberGeneration);
			
			this.adminService.update(this.selectedAgentType);

			if(!this.selectedRound.getAgentTypes().contains(this.selectedAgentType)){
				this.selectedRound.addAgentType(this.selectedAgentType);
			}
			
			//create Agents
			
			generateAndSaveAgentFromAgentType(this.selectedAgentType,adminService.getSetting());		
			
			return "adminAgentTypeManagement?faces-redirect=true";
		}
		catch (ConstraintViolationException e) {
			this.selectedRound=(Round)adminService.refresh(selectedRound);
			this.addErrorMessage("Error at saving AgentType: Name of the AgentType should only exist one time per Round!");
			return "";
		}
		catch (RuntimeException e){
			e.printStackTrace();
			this.addErrorMessage("Error at saving AgentType: "+e.getMessage());
			return "";
		}
    }
	
	public void generateAndSaveAgentFromAgentType(AgentType at,Setting setting){
		Agent agent=null;
		GaussianNumberGenerator gaussian = new GaussianNumberGenerator();
		
		for(int i=1;i<=at.getAmount();i++){
			agent=new Agent(at.getAgentName()+" - "+i);
			double preferencePrice=gaussian.getRandomGaussianValueRange(at.getMeanPrice(), setting.getPreferenceVariance(),0.0,1.0);
			double preferenceImage=gaussian.getRandomGaussianValueRange(at.getMeanImage(), setting.getPreferenceVariance(),0.0,1.0);
			double preferenceQuality=gaussian.getRandomGaussianValueRange(at.getMeanQuality(), setting.getPreferenceVariance(),0.0,1.0);
			agent.setPreferencePrice(preferencePrice);
			agent.setPreferenceImage(preferenceImage);
			agent.setPreferenceQuality(preferenceQuality);
			agent.setAgentType(at);
			this.adminService.update(agent);
		}
	}
	
	
	
	
	public String actionUpdateUser() {
		try{
			this.selectedUser.setNickname(this.userName);
			this.selectedUser.setEmail(this.userMail);
			
			//just if user want to change the password
			if(setPassword){
				byte[] bSalt=SecurityUtil.createSalt();
				String salt=SecurityUtil.encodeBase64(bSalt);
				this.selectedUser.setSalt(salt);
				byte[] bHash=SecurityUtil.getHash(this.userPassword, bSalt);			
				String password=SecurityUtil.encodeBase64(bHash);
				this.selectedUser.setPassword(password);
			}
			
			if(setImageBudget){
				this.selectedUser.setImageValue(this.userImage);
				this.selectedUser.setBudget(this.userBudget);
			}
			
			if(this.selectedUser.getPassword()==null || this.selectedUser.getPassword().isEmpty()){
				throw new RuntimeException("Password missing!");
			}
			
			this.adminService.update(this.selectedUser);
			
			if(!this.selectedGame.getUsers().contains(this.selectedUser)){
				this.selectedGame.addUser(this.selectedUser);
			}
			
			this.userPassword="";
			
			this.selectedGame.getUsers();
			
			return "adminUserManagement?faces-redirect=true";
		}
		catch (NoSuchAlgorithmException e) {
			this.addErrorMessage("Error at saving User: "+e.getMessage());
			return "";
		} catch (UnsupportedEncodingException e) {
			this.addErrorMessage("Error at saving User: "+e.getMessage());
			return "";
		} catch (ConstraintViolationException e) {
			this.selectedGame=(Game)adminService.refresh(this.selectedGame);
			this.addErrorMessage("Error at saving User: Name of the user should only exist once for all games!");
			return "";
		}
		catch (RuntimeException e){
			this.addErrorMessage("Error at saving User: "+e.getMessage());
			return "";
		} 
		finally{
			setPassword=false;
			setImageBudget=false;
		}
    }
	
	public String actionUpdateRound() {
		try{
			this.selectedRound.setStartDate(this.roundStartDate);
			this.selectedRound.setEndDate(this.roundEndDate);
			this.selectedRound.setRoundNumber(this.roundNumber);
			this.selectedRound.setGame(this.selectedGame);
			
			this.adminService.update(this.selectedRound);
			
			if(this.selectedGame.getRounds()==null)
				this.selectedGame.setRounds(new ArrayList<Round>());
			
			if(!this.selectedGame.getRounds().contains(this.selectedRound)){
				this.selectedGame.addRound(this.selectedRound);
			}
						
			this.roundStartDate=null;
			this.roundEndDate=null;
			return "adminRoundManagement?faces-redirect=true";
		}
		catch (ConstraintViolationException e) {
			this.selectedGame=(Game)adminService.refresh(this.selectedGame);
			this.addErrorMessage("Error at saving Round: StartDate have to be before the EndDate and Roundnumber has to be unique in the game!");
			return "";
		}
		catch (RuntimeException e){
			if(e.getMessage().contains("_this.startDate.before(_this.endDate)")){
				this.selectedGame=(Game)adminService.refresh(this.selectedGame);
				this.addErrorMessage("Error at saving Round: StartDate have to be before the EndDate!");
			}
			else if(e.getMessage().contains("Duplicate entry")){
				this.selectedGame=(Game)adminService.refresh(this.selectedGame);
				this.addErrorMessage("Round Number has to be unique in the game.");
			}
			else{
				this.addErrorMessage("Error at saving Round: "+e.getMessage());
				e.printStackTrace();
			}
			return "";
		}
	}
	
	
	public String actionUpdateProduct() {
		try{
			this.selectedProduct.setName(this.productName);
			this.selectedProduct.setProductCosts(this.productCosts);
			this.selectedProduct.setImageFactor(this.productImageFactor);
			this.selectedProduct.setQualityFactor(this.productQualityFactor);
			this.selectedProduct.setActive(this.productActive);
				
			Integer id=Integer.parseInt(this.productSupplierId);
			Supplier supp=this.adminService.getSupplierById(id);
			this.selectedProduct.setSupplier(supp);
			
			allProducts=null;
			this.adminService.update(this.selectedProduct);


			return "adminProductManagement?faces-redirect=true";
		}
		catch (ConstraintViolationException e) {
			this.addErrorMessage("Error at saving Product: "+e.getCause().getMessage());
			return "";
		}
		catch (RuntimeException e){
			this.addErrorMessage("Error at saving Product: "+e.getMessage());
			e.printStackTrace();
			return "";
		}
	}
	
	
	public String actionUpdateSupplier() {
		try{
			this.selectedSupplier.setSupplierName(this.supplierName);
			this.selectedSupplier.setDiscountPerTenUnits(this.supplierDiscountPer10Units);
			this.selectedSupplier.setDeliveryCost(this.supplierDeliveryCosts);
			this.selectedSupplier.setActive(this.supplierActive);
				
			this.adminService.update(this.selectedSupplier);
			allSuppliers=null;
			
			return "adminSupplierManagement?faces-redirect=true";
		}
		catch (ConstraintViolationException e) {
			this.addErrorMessage("Error at saving Supplier: "+e.getCause().getMessage());
			return "";
		}
		catch (RuntimeException e){
			this.addErrorMessage("Error at saving Supplier: "+e.getMessage());
			e.printStackTrace();
			return "";
		}
	}
	
	public String actionAbortRound() {		
		this.addInfoMessage("Change aborted!");
		
		return "adminRoundManagement?faces-redirect=true";
    }
	
	public String actionAbortUser() {		
		this.addInfoMessage("Change aborted!");
		
		return "adminUserManagement?faces-redirect=true";
    }
	
	public String actionAbortProduct() {		
		this.addInfoMessage("Change aborted!");
		
		return "adminProductManagement?faces-redirect=true";
    }
	
	public String actionAbortSupplier() {		
		this.addInfoMessage("Change aborted!");
		
		return "adminSupplierManagement?faces-redirect=true";
    }
	
	public String actionUpdateGameName(){
		this.selectedGame.setName(this.gameName);
		System.out.println("------- actionUpdateGameName");
		try{
			this.adminService.update(this.selectedGame);
		}
		catch (ConstraintViolationException e) {
			this.addErrorMessage("Error at saving Game: "+e.getCause().getMessage());
			return "";
		}
		catch (RuntimeException e){
			this.addErrorMessage("Error at saving Game: "+e.getMessage());
			e.printStackTrace();
			return "";
		}
		this.allGames=this.adminService.getAllGames();
		return "adminGameManagement?faces-redirect=true";
	}
	
	
	public String actionUpdateGame() {
		System.out.println("------- actionUpdateGame");
		try{
			Game game=new Game(this.gameName,this.startDate,new Date(),(double)this.roundTime);
			this.adminService.create(game);
			Setting setting=adminService.getSetting();
			
			//Create Rounds for the game
			for(int i=0;i<this.numberRounds;i++){
				Calendar cal = Calendar.getInstance(); // creates calendar
			    cal.setTime(this.startDate); // sets calendar time/date
			    cal.add(Calendar.HOUR_OF_DAY, (this.roundTime*(int)i)); // adds one hour
			    Date roundStartTime=cal.getTime();
			    
			    cal.setTime(roundStartTime); // sets calendar time/date
			    cal.add(Calendar.HOUR_OF_DAY, this.roundTime); // adds one hour
			    Date roundEndTime=cal.getTime();
			    
				Round round=new Round((i+1), roundStartTime,roundEndTime);
				round.setPlayed(false);
				round.setGame(game);
				this.adminService.create(round);
				game.addRound(round);
			}
			
			//create users for the game
			try {
				for(int i=1;i<=this.gameUsersAmount;i++){
					User u=new User();
					u.setAdmin(false);
					u.setEmail("dummy@dummy.at");
					u.setNickname(game.getName()+"_Company_"+i);
					u.setImageValue(setting.getStartImageForCompanies());  //setted from DB
					byte[] bSalt=SecurityUtil.createSalt();
					String salt=SecurityUtil.encodeBase64(bSalt);
					u.setSalt(salt);
					byte[] bHash;
					bHash = SecurityUtil.getHash("start123", bSalt);
						
					String password=SecurityUtil.encodeBase64(bHash);
					u.setPassword(password);
					u.setGame(game);
					u.setBudget(setting.getStartBudgetForCompanies());
					u.setImageValue(setting.getStartImageForCompanies());
					
					this.adminService.create(u);
					game.addUser(u);
					
				}
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}		
			
			this.allGames=this.adminService.getAllGames();
			
			return "adminGameManagement?faces-redirect=true";
		}
		catch (ConstraintViolationException e) {
			this.addErrorMessage("Error at saving Game: "+e.getCause().getMessage());
			return "";
		}
		catch (RuntimeException e){
			this.addErrorMessage("Error at saving Game: "+e.getMessage());
			e.printStackTrace();
			return "";
		}
    }
	
	public String actionAbortAgentType() {		
		this.addInfoMessage("Change aborted!");
		
		return "adminAgentTypeManagement?faces-redirect=true";
    }
	
	public String actionAbortGame() {		
		this.addInfoMessage("Change aborted!");
		
		return "adminGameManagement?faces-redirect=true";
    }

	public Round getSelectedRound() {
		return selectedRound;
	}

	public void setSelectedRound(Round selectedRound) {
		this.selectedRound = selectedRound;
	}

	public AgentType getSelectedAgentType() {
		return selectedAgentType;
	}

	public void setSelectedAgentType(AgentType selectedAgentType) {
		this.selectedAgentType = selectedAgentType;
		this.agentTypeAgents=null;
	}

	public User getSelectedUser() {
		return selectedUser;
	}

	public void setSelectedUser(User selectedUser) {
		this.selectedUser = selectedUser;
	}

	public String getAgentName() {
		return agentName;
	}

	public void setAgentName(String agentName) {
		this.agentName = agentName;
	}

	public String getGameName() {
		return gameName;
	}

	public void setGameName(String gameName) {
		this.gameName = gameName;
	}

	public Date getStartDate() {
		return startDate;
	}

	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}

	public Integer getRoundTime() {
		return roundTime;
	}

	public void setRoundTime(Integer roundTime) {
		this.roundTime = roundTime;
	}

	public Integer getNumberRounds() {
		return numberRounds;
	}

	public void setNumberRounds(Integer numberRounds) {
		this.numberRounds = numberRounds;
	}

	public Date getRoundStartDate() {
		return roundStartDate;
	}

	public void setRoundStartDate(Date roundStartDate) {
		this.roundStartDate = roundStartDate;
	}

	public Date getRoundEndDate() {
		return roundEndDate;
	}

	public void setRoundEndDate(Date roundEndDate) {
		this.roundEndDate = roundEndDate;
	}

	public Integer getRoundNumber() {
		return roundNumber;
	}

	public void setRoundNumber(Integer roundNumber) {
		this.roundNumber = roundNumber;
	}
	
	
	public Product getSelectedProduct() {
		return selectedProduct;
	}


	public void setSelectedProduct(Product selectedProduct) {
		this.selectedProduct = selectedProduct;
	}


	public void eventLoadTableData(ActionEvent actionEvent){
		Map<String, String> colMap=null;
		
		switch (this.selectedReportOption) {
	        case Constants.OPTION_ALL_ROUND_DATA:
	        	this.tableData=this.adminService.getMarketGameRoundDecisions(this.selectedGame);
	        	
	        	colMap = new LinkedHashMap <String,String>();
	    		colMap.put("company_nickname","Company");
	    		colMap.put("round_number","Round");
	    		colMap.put("decres_newBudget","Round Budget");
	    		colMap.put("decres_revenue","Revenue");
	    		colMap.put("decres_expenses","Expenses");
	    		colMap.put("decres_marketingInvestment","Marketing Investment");
	    		colMap.put("decres_employerEducationInvestment","Education Investment");
	    		colMap.put("decres_rdInvestment","R&D Investment");
	    		colMap.put("decres_logisticCosts","Logistic Costs");
	    		colMap.put("decres_overdraftCosts","Overdraft Costs");
	    		colMap.put("decres_reportCosts","Report Costs");
	    		colMap.put("decres_newImage","New Image");
	    		colMap.put("report_name","Report");
	    		
	    		this.columns.clear();
	    		this.columns.addAll(ColumnModel.populateColumnsHM(colMap));

	            break;
	        case Constants.OPTION_ALL_AGENT_DATA:
	        	this.tableData=this.adminService.getAgentRoundInformation(this.selectedGame);
	        	
	        	colMap = new LinkedHashMap <String,String>();
	    		colMap.put("agType_agentName","Agenttype");
	    		colMap.put("round_number","Round");
	    		colMap.put("company_nickname","Company");
	    		colMap.put("product_name","Product");
	    		colMap.put("supplier_name","Supplier");
	    		colMap.put("product_productCosts","Product Costs");
	    		colMap.put("compprod_sellingPrice","Selling Price");
	    		colMap.put("agent_preferenceQuality","Pref Quality");
	    		colMap.put("agent_preferencePrice","Pref Price");
	    		colMap.put("agent_preferenceImage","Pref Image");
	    		
	    		this.columns.clear();
	    		this.columns.addAll(ColumnModel.populateColumnsHM(colMap));
	    		
	            break;
	        case Constants.OPTION_ALL_COMPANY_PRODUCT:
	        	this.tableData=this.adminService.getMarketGameCompanyProducts(this.selectedGame);
	        	
	        	colMap = new LinkedHashMap <String,String>();
	    		colMap.put("product_name","Name");
	    		colMap.put("supplier_name","Supplier");
	    		colMap.put("round_number","Round");
	    		colMap.put("company_nickname","Company");	
	    		colMap.put("decres_newImage","Round Image");
	    		colMap.put("product_productCosts","Product Costs");
	    		colMap.put("compprod_sellingPrice","Selling Price");
	    		colMap.put("product_qualityFactor","Quality Factor");  	
	    		colMap.put("amountCompanyProducts", "Amount Sold");
	    		//colMap.put("product_imageFactor","Image Factor");
	    		
	    		this.columns.clear();
	    		this.columns.addAll(ColumnModel.populateColumnsHM(colMap));
	    		
	            break; 
	        case Constants.OPTION_ALL_PRODUCTS_FROM_SUPPLIERS:
	        	this.tableData=this.adminService.getMarketGameProducts();
	        	
	        	colMap = new LinkedHashMap <String,String>();
	    		colMap.put("product_name","Name");
	    		colMap.put("supplier_name","Supplier");	
	    		colMap.put("product_productCosts","Product Costs");
	    		colMap.put("product_qualityFactor","Quality Factor");  		
	    		//colMap.put("product_imageFactor","Image Factor");
	    		
	    		this.columns.clear();
	    		this.columns.addAll(ColumnModel.populateColumnsHM(colMap));
	    		
	            break;             
	        case Constants.OPTION_ALL_AGENTTYPE_COMPANY_SALES:
	        	this.tableData=this.adminService.getMarketGameAgentTypeSales(this.selectedGame);
	        	
	        	colMap = new LinkedHashMap <String,String>();
	    		
	        	colMap.put("agent_name", "AgentType");
	        	colMap.put("round_number","Round");
	        	colMap.put("product_name","Product");
	    		colMap.put("supplier_name","Supplier");	
	    		colMap.put("company_nickname","User"); 
	    		colMap.put("compprod_amountSold","Amount Sold");
	    			
	    		this.columns.clear();
	    		this.columns.addAll(ColumnModel.populateColumnsHM(colMap));
	    		
	            break;     
	
	        default:
	            throw new IllegalArgumentException("Invalid Option "+selectedReportOption);
		}		
	}
	
	public void eventLoadChartData(ActionEvent actionEvent){	
		Setting setting=null;
		
		switch (this.selectedChartOption) {
	        case Constants.OPTION_ALL_COMPANY_BUDGET:
	        	this.chartData=adminService.getMarketGameBudgetChart(this.selectedGame);
	        	this.chartType=Constants.CHART_BAR;
	            break;
	        case Constants.OPTION_ALL_COMPANY_IMAGE:
	        	this.chartData=adminService.getMarketGameImageChart(this.selectedGame);
	        	this.chartType=Constants.CHART_BAR;
	            break;
	        case Constants.OPTION_ALL_COMPANY_ROUND_REVENUE:
	        	this.chartData=adminService.getMarketGameRoundDecisionRevenue(this.selectedGame);
	        	this.chartType=Constants.CHART_LINE;
	            break;
	        case Constants.OPTION_ALL_COMPANY_ROUND_BUDGET:
	        	this.chartData=adminService.getMarketGameRoundDecisionBudget(this.selectedGame);
	        	this.chartType=Constants.CHART_LINE;
	            break;
	        case Constants.OPTION_ALL_COMPANY_IMAGE_EVOLUTION:
	        	setting=adminService.getSetting();
	        	this.chartData=adminService.getMarketGameImageDevelopment(this.selectedGame,setting);
	        	this.chartType=Constants.CHART_LINE;
	        	break;
	        case Constants.OPTION_ALL_COMPANY_SELLING_EVOLUTION:
	        	this.chartData=adminService.getMarketGameSellingsDevelopment(this.selectedGame);
	        	this.chartType=Constants.CHART_LINE;
	        	break;		
	        case Constants.OPTION_ALL_COMPANY_TOPSELLER:
	        	this.chartData=adminService.getMarketGameTopSellingsChart(this.selectedGame, 5);
	        	this.chartType=Constants.CHART_BAR;
	            break; 
	        case Constants.OPTION_ALL_COMPANY_ROUND_MARKETING_INVESTMENT:
	        	this.chartData=adminService.getMarketGameRoundDecisionMarketingInvestment(this.selectedGame);
	        	this.chartType=Constants.CHART_LINE;
	            break; 
	        case Constants.OPTION_ALL_COMPANY_ROUND_EDUCATION_INVESTMENT:
	        	this.chartData=adminService.getMarketGameRoundDecisionEducationInvestment(this.selectedGame);
	        	this.chartType=Constants.CHART_LINE;
	            break;    
	        case Constants.OPTION_ALL_COMPANY_ROUND_OVERDRAFT_COSTS:
	        	this.chartData=adminService.getMarketGameRoundDecisionOverdraftCosts(this.selectedGame);
	        	this.chartType=Constants.CHART_LINE;
	            break;   
	        case Constants.OPTION_ALL_COMPANY_ROUND_LOGISTIC_COSTS:
	        	this.chartData=adminService.getMarketGameRoundDecisionLogisticCosts(this.selectedGame);
	        	this.chartType=Constants.CHART_LINE;
	            break;       
	        case Constants.OPTION_ALL_COMPANY_ROUND_EXPENSES:
	        	this.chartData=adminService.getMarketGameRoundDecisionExpenses(this.selectedGame);
	        	this.chartType=Constants.CHART_LINE;
	            break; 
	        case Constants.OPTION_ALL_COMPANY_ROUND_AGENTTYPE:
	        	this.chartData=adminService.getMarketGameAgenttypeAmount(this.selectedGame);
	        	this.chartType=Constants.CHART_LINE;
	            break; 
	        case Constants.OPTION_ALL_PORTFOLIO_RISING:
	        	setting=adminService.getSetting();
	        	this.chartData=adminService.getMarketPortfolioCostsCurve(setting);
	        	this.chartType=Constants.CHART_LINE;
	            break; 
	            
	        default:
	            throw new IllegalArgumentException("Invalid Option: "+selectedReportOption);
		}		
	}
	
	

	public List<ColumnModel> getColumns() {
		return columns;
	}

	public List<StatisticBean> getMarketGameRoundDecisions() {
		return tableData;
	}

	public void setMarketGameRoundDecisions(
			List<StatisticBean> marketGameRoundDecisions) {
		this.tableData = marketGameRoundDecisions;
	}

	public List<SelectItem> getReportOptions() {
		return reportOptions;
	}


	public void setReportOptions(List<SelectItem> reportOptions) {
		this.reportOptions = reportOptions;
	}


	public String getSelectedReportOption() {
		return selectedReportOption;
	}

	public void setSelectedReportOption(String selectedOption) {
		this.selectedReportOption = selectedOption;
	}


	public List<StatisticBean> getTableData() {
		return tableData;
	}


	public void setTableData(List<StatisticBean> tableData) {
		this.tableData = tableData;
	}


	public List<SelectItem> getChartOptions() {
		return chartOptions;
	}


	public void setChartOptions(List<SelectItem> chartOptions) {
		this.chartOptions = chartOptions;
	}


	public String getSelectedChartOption() {
		return selectedChartOption;
	}


	public void setSelectedChartOption(String selectedChartOption) {
		this.selectedChartOption = selectedChartOption;
	}


	public ChartModel getChartData() {
		return chartData;
	}


	public void setChartData(ChartModel chartData) {
		this.chartData = chartData;
	}


	public String getChartType() {
		return chartType;
	}


	public void setChartType(String chartType) {
		this.chartType = chartType;
	}


	public String getUserName() {
		return userName;
	}


	public void setUserName(String userName) {
		this.userName = userName;
	}


	public String getUserMail() {
		return userMail;
	}


	public void setUserMail(String userMail) {
		this.userMail = userMail;
	}


	public String getUserPassword() {
		return userPassword;
	}


	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}


	public Integer getGameUsersAmount() {
		return gameUsersAmount;
	}


	public void setGameUsersAmount(Integer gameUsersAmount) {
		this.gameUsersAmount = gameUsersAmount;
	}
	
	public List<Supplier> allSuppliers() {
		if(allSuppliers==null)
			this.allSuppliers=this.adminService.getAllSuppliers();
		return adminService.getAllSuppliers();
	}
	
	public List<News> getTopAdminNews(){
		return adminService.getLastNewsForGame(null, 10);
	}
	
	public List<News> getAdminNews(){
		return adminService.getLastNewsForGame(null, null);
	}


	public String getNewsText() {
		return newsText;
	}

	public void setNewsText(String newsText) {
		this.newsText = newsText;
	}
	
	
	public String actionSendMessage() {		
		Integer gameId=Integer.parseInt(this.gameId);
		
		News news=new News(this.newsText,gameId);
		news.setNewsDate(new Date());
		news.setHeader(Constants.INFO_HEADER);
		
		this.adminService.update(news);
		this.addInfoMessage("News has been sent!");
		this.newsText=null;
		return "";
    }


	public String getGameId() {
		return gameId;
	}


	public void setGameId(String gameId) {
		this.gameId = gameId;
	}


	public String getProductName() {
		return productName;
	}


	public void setProductName(String productName) {
		this.productName = productName;
	}


	public Double getProductImageFactor() {
		return productImageFactor;
	}


	public void setProductImageFactor(Double productImageFactor) {
		this.productImageFactor = productImageFactor;
	}


	public Double getProductQualityFactor() {
		return productQualityFactor;
	}


	public void setProductQualityFactor(Double productQualityFactor) {
		this.productQualityFactor = productQualityFactor;
	}


	public Double getProductCosts() {
		return productCosts;
	}


	public void setProductCosts(Double productCosts) {
		this.productCosts = productCosts;
	}


	public String getProductSupplierId() {
		return productSupplierId;
	}


	public void setProductSupplierId(String productSupplierId) {
		this.productSupplierId = productSupplierId;
	}


	public boolean isProductActive() {
		return productActive;
	}


	public void setProductActive(boolean productActive) {
		this.productActive = productActive;
	}


	public boolean isSetPassword() {
		return setPassword;
	}


	public void setSetPassword(boolean setPassword) {
		this.setPassword = setPassword;
	}


	public String getSupplierName() {
		return supplierName;
	}


	public void setSupplierName(String supplierName) {
		this.supplierName = supplierName;
	}


	public Double getSupplierDiscountPer10Units() {
		return supplierDiscountPer10Units;
	}


	public void setSupplierDiscountPer10Units(Double supplierDiscountPer10Units) {
		this.supplierDiscountPer10Units = supplierDiscountPer10Units;
	}


	public Double getSupplierDeliveryCosts() {
		return supplierDeliveryCosts;
	}


	public void setSupplierDeliveryCosts(Double supplierDeliveryCosts) {
		this.supplierDeliveryCosts = supplierDeliveryCosts;
	}


	public boolean isSupplierActive() {
		return supplierActive;
	}


	public void setSupplierActive(boolean supplierActive) {
		this.supplierActive = supplierActive;
	}


	public Supplier getSelectedSupplier() {
		return selectedSupplier;
	}


	public void setSelectedSupplier(Supplier selectedSupplier) {
		this.selectedSupplier = selectedSupplier;
	}


	public List<Setting> getSettings() {
		if(settings==null || settings.size()==0){
			settings=new ArrayList<Setting>();
			Setting setting=adminService.getSetting();
			settings.add(setting);
		}
			
		return settings;
	}

	public void actionRefreshSettings(){
		settings=new ArrayList<Setting>();
		Setting setting=adminService.getSetting();
		settings.add(setting);
	}
	
	/**
	 * Saving and refreshing the CompanyProductList, especially to 
	 * update the selling price.
	 * @return
	 */
	public void actionSaveAndRefreshSetting(ActionEvent actionEvent){
		for (Setting setting : this.settings) {
			this.adminService.update(setting);
		}
		this.addInfoMessage(Constants.CMB_SETTING_UPDATE);
	}
	
	public void setSettings(List<Setting> settings) {
		this.settings = settings;
	}

	
	public int getAgentAmountRecommendation(){
		Setting setting = adminService.getSetting();
		int amount=0;
		if(this.selectedGame!=null && this.selectedGame.getUserList()!=null && setting.getAgentAmountCompanyFactor()!=null){
			int amountUsers=this.selectedGame.getUserList().size();
			amount=setting.getAgentAmountCompanyFactor().intValue()*amountUsers;
		}
		
		return amount;
	}


	public boolean isSetImageBudget() {
		return setImageBudget;
	}


	public void setSetImageBudget(boolean setImageBudget) {
		this.setImageBudget = setImageBudget;
	}


	public Double getUserImage() {
		return userImage;
	}


	public void setUserImage(Double userImage) {
		this.userImage = userImage;
	}


	public Double getUserBudget() {
		return userBudget;
	}


	public void setUserBudget(Double userBudget) {
		this.userBudget = userBudget;
	}
	
}
